#include <iostream>
using std::cout;
using std::endl;

#define PI "hello"

void test0(){
    //const修饰内置类型
    //添加只读限定
    const double pi = 3.14;
    /* const double pi = "hello"; */
    int const num = 100;

    //不允许写操作
    /* pi = 23.8; */
    /* num = 300; */
    cout << pi << endl;
    cout << num << endl;

    int val;
    val = 100;

    //const常量在定义时必须初始化
    /* const int val2; */
    /* val2 = 200; */
}

void test1(){
    //const在*号左边，可以理解为修饰的就是指针指向的内容
    //可以修改指针的指向
    //不能通过指针修改其指向的内容
    //称为“指向常量的指针” —— pointer to const
    int num1 = 100;
    int num2 = 200;
    const int * p1 = &num1;
    /* num1 = 400;//ok */
    /* *p1 = 400; */
    p1 = &num2;
    cout << *p1 << endl;


    //还有一个意义
    //只有指向常量的指针才能去指向const常量
    const int num3 = 1;
    /* int * p2 = &num3; */
    const int * p2 = &num3;
    /* *p2 = 2; */
    //指向常量的指针不仅能够指向const常量
    //还可以指向普通的变量
    p2 = &num2;
}

void test2(){
    int num1 = 100;
    int num2 = 200;
    int const * p1 = &num1;
    //可以修改指向
    //不能通过指针修改其指向的内容
    /* num1 = 400;//ok */
    /* *p1 = 400; */
    p1 = &num2;
    cout << *p1 << endl;
}

void test3(){
    //const写在*号的右边，可以理解为const修饰的是指针本身
    //记录的地址不能修改
    //可以通过指针修改其指向的值
    //不能修改指向
    //称之为常量指针,可以从右往左看
    //先看到const，再看到*（const pointer）
    int num1 = 100;
    int num2 = 200;
    int * const p1 = &num1;
    *p1 = 300;
    cout << num1 << endl;
    /* p1 = &num2; */

    /* const int num3 = 1; */
    int num3 = 1;
    const int * const p2 = &num3;
    /* *p2 = 1000;//前一个const限定的效果 */
    /* p2 = &num2;//后一个const限定的效果 */
}

//数组指针
//指向数组的指针，管理权是整个数组空间
void test4(){
    int arr[5] = {1,2,3,4,5};
    //数组首元素的首地址
    //偏移一个元素的长度
    cout << arr + 1 << endl;
    //数组的首地址
    //偏移整个数组的长度
    cout << &arr + 1 << endl;
    /* int * p = arr; */
    /* int * p2 = &arr; */
    int (*p)[5] = &arr;//数组指针
    for(int idx = 0; idx < 5; ++idx){
        cout << (*p)[idx] << " ";
    }
    cout << endl;
}

//指针数组
//元素为指针的数组
void test5(){
    int num1 = 4, num2 = 5, num3 = 6;
    int * p1 = &num1;
    int * p2 = &num2;
    int * p3 = &num3;
    int * arr[3] = {p1,p2,p3};
    for(int idx = 0; idx < 3; ++idx){
        cout << *arr[idx] << " ";
    }
    cout << endl;
}

void print(){
    cout << "print()" << endl;
}

void show(){
    cout << "show()" << endl;
}
int display(int x,int y){
    return x + y;
}

//函数指针
void test6(){
    //定义函数指针时要确定指向的函数类型和参数信息
    void (*p)() = print;
    p();

    //完整写法
    void (*p2)() = &print;
    (*p2)();

    /* p2 = display; */
    p2 = show;
    p2();

    int (*p3)(int,int) = &display;
    cout << (*p3)(4,5) << endl;
}

//指针函数
//要确保返回的指针所指向的变量的生命周期
//比函数的生命周期更长
int Num = 600;

int * f(){
    return &Num;
}

void test7(){
    cout << *f() << endl;
}


int main(void){
    test7();
    return 0;
}
